package com.siecom.framework.plugin.cipherkeyboard.kmy;

import android.util.Log;

import com.siecom.framework.channel.ChannelInstance;
import com.siecom.tools.ByteTool;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by zhq on 2015/12/24.
 */
public class KeyboardApi {
    public final int RECV_PACKET_ERROR = -2509;
    byte[] RecvBuff = new byte[2176];
    int[] RecvLen = new int[1];



    public int readEncryptPwd(byte[] buf){
        int ret = SendPacket("42", "");
        ret = RecvPacket(RecvBuff, RecvLen, 3000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        int[] len = new int[1];
        len[0] = by.length - 2;
        System.arraycopy(by, 2, buf, 0, 16);
        return 0;

    }
    /**
     * EncryptMode 说明
     *
     00:由算法参数决定加密模式，后加密模式，可 在PIN输入完成后再设置加密模式
     01:PIN与CARD-NO进行运算后加密（ISO9564-1 格式0或ANSI X9.8）
     02:PIN不与CARD-NO进行运算，使用PIN ASCII 码加密。(ASCII格式)
     03: PIN不与CARD-NO进行运算，使用PIN BCD码 加密。(IBM3624格式)
     workKeyData 随机的工作密钥 8位，没有就""
     * @param PinLen
     * @param EncryptMode
     * @param timeOut
     * @param workKeyData
     * @return
     */
    public int startEncrypt(String PinLen,String EncryptMode,String timeOut,String workKeyData){
        int ret = SendPacket("35", PinLen+"01"+EncryptMode+"00"+timeOut+workKeyData);
        ret = RecvPacket(RecvBuff, RecvLen, 3000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        return 0;


    }

    /**
     *用于设置卡号或者传输码
     * @param MainKeyIndex
     * @param workKeyIndex
     * @param data
     * @return
     */
    public int setCardNoOrTransCode(String MainKeyIndex,String workKeyIndex,String data){
        int ret = SendPacket("34", MainKeyIndex + workKeyIndex + data);
        ret = RecvPacket(RecvBuff, RecvLen, 3000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        return 0;

    }

    /**
     * 灌入工作密钥SAM卡操作
     * :M对应主密钥号， N对应工作密钥号，SLOT对应SAM卡的卡槽(1-4)，
     * PWD对应SAM卡验证密钥, 工 作密钥密文WP为8字节(对应DES)。
     * 选择SAM卡座失败  返回ST=0xE1
     * 给SAM卡座上电失败  返回ST=0xE2   验证SAM卡密码失败
     * 返回ST=0xE3   SAM选择DF01目录失败 返回ST=0xE4   SAM卡解密初始化失败 返回ST=0xE5
     * SAM卡解密工作密钥失败 返回ST=0xE6   保存工作密钥失败  返回ST=0xE7   SAM卡座下电失败
     * S返回ST=0xE8
     *
     * @return
     */
    public int injectionWorkKeyInSAM(String MainKeyIndex, String workKeyIndex, String slot, String pwd, String workKey) {
        int ret = SendPacket("71", MainKeyIndex + workKeyIndex + slot+pwd+workKey);
        ret = RecvPacket(RecvBuff, RecvLen, 3000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        return 0;

    }

    /**
     * 注入工作密钥
     *
     * @param MainKeyIndex
     * @param workKeyIndex
     * @param workKey
     * @return
     */

    public int injectionWorkKey(String MainKeyIndex, String workKeyIndex, String workKey) {
        int ret = SendPacket("33", MainKeyIndex + workKeyIndex + workKey);
        ret = RecvPacket(RecvBuff, RecvLen, 3000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        return 0;

    }

    /**
     * 注入主密钥
     *
     * @return
     */
    public int injectionMainKey(String keyIndex, String keyData) {
        int ret = SendPacket("32", keyIndex + keyData);
        ret = RecvPacket(RecvBuff, RecvLen, 3000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        return 0;
    }

    /**
     * 重置机器，是否需要清除密钥
     *
     * @param clearKey
     * @return
     */
    public int reset(boolean clearKey) {
        int ret = 0;
        if (clearKey) {
            ret = SendPacket("31", "38");
        } else {
            ret = SendPacket("31", "39");
        }
        ret = RecvPacket(RecvBuff, RecvLen, 5000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        return 0;
    }

    /**
     * 获取版本号
     *
     * @param buf
     * @param len
     * @return
     */
    public int getVersion(byte[] buf, int[] len) {
        int ret = SendPacket("30", "");
        ret = RecvPacket(RecvBuff, RecvLen, 1000);
        String hexStr = new String(RecvBuff, 0, RecvLen[0]).trim();
        byte[] by = ByteTool.hexStr2Bytes(hexStr);
        ret = by[1];
        if (ret != (byte) 0x04) {
            Log.e("ret:", Integer.toHexString(ret));
            return 0 - ret;
        }
        len[0] = by.length - 2;
        System.arraycopy(by, 2, buf, 0, 16);
        return ret;
    }

    public int RecvPacket(byte[] pbyRecvData, int[] pwPacketetLen,
                          int dwTimeoutMs) {
        int wDataLen = 0;
        int byRet = RecvBytes(pbyRecvData, 0, 1, dwTimeoutMs);
        if ((1 != byRet) || (0x02 != pbyRecvData[0])) {
            return -1;
        }

        byRet = RecvBytes(pbyRecvData, 1, 2, 200);
        if (2 != byRet) {
            return RECV_PACKET_ERROR;
        }

        byte[] len = new byte[2];
        len[0] = pbyRecvData[1];
        len[1] = pbyRecvData[2];
        wDataLen = Integer.parseInt(new String(len), 16);
        Log.e("len", wDataLen + "===");
        pwPacketetLen[0] = (wDataLen * 2 + 5);
        if (wDataLen > 2176) {
            return -2511;
        }
        byRet = RecvBytes(pbyRecvData, 3, wDataLen * 2 + 2, 500);
        if (wDataLen * 2 + 2 != byRet) {
            return RECV_PACKET_ERROR;
        }
        Log.e("KeyboardApi:" + byRet, ByteTool.bytearrayToHexString(RecvBuff, RecvLen[0]));
        return 0;
    }

    public int RecvBytes(byte[] rspMsg, int index, int wantedLen, int timeOutMs) {

        byte[] tempBuf = new byte[wantedLen];
        int ret = ChannelInstance.receiveBytes(tempBuf, wantedLen, timeOutMs);
        if (ret < 0) {
            return ret;
        }
        System.arraycopy(tempBuf, 0, rspMsg, index, ret);
        return ret;
    }

    public int SendPacket(String cmd, String data) {
        List<byte[]> srcArrays = new ArrayList<byte[]>();
        String total = cmd + data;
        int ln = total.length() / 2;
        String len = Integer.toHexString(ln).toUpperCase();
        if (len.length() == 1) {
            len = '0' + len;
        }
        total = len + total;
        byte[] tmp = ByteTool.hexStr2Bytes(total);
        byte[] header = new byte[1];
        header[0] = (byte) 02;
        srcArrays.add(header);
        srcArrays.add(tmp);
        total = total + getBCC(tmp);
        srcArrays.clear();
        srcArrays.add(header);
        try {
            srcArrays.add(total.getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        byte[] rs = ByteTool.streamCopy(srcArrays);
        return ChannelInstance.sendBytes(rs, rs.length);
    }

    /**
     * BCC
     *
     * @param data
     * @return
     */
    public static String getBCC(byte[] data) {

        String ret = "";
        byte BCC[] = new byte[1];
        for (int i = 0; i < data.length; i++) {
            BCC[0] = (byte) (BCC[0] ^ data[i]);
        }
        String hex = Integer.toHexString(BCC[0] & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        ret += hex.toUpperCase();
        return ret;
    }
}
